package socket.socketByNetty.client;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.timeout.IdleStateHandler;

import java.nio.charset.Charset;
import java.util.concurrent.TimeUnit;

/**
 * Created by think on 2017/10/30.
 */
public class EchoClient {
    private static String host;
    private static int port;
    private static int reConnectCount = 0;
    private static final int MAX_RECONNECTCOUNT = 5;
    public static Bootstrap bootstrap;

    public EchoClient(String host, int port){
        this.host = host;
        this.port = port;
    }

    public static void start() {
        ChannelFuture future = null;
        EventLoopGroup eventLoopGroup = null;
        try {
            eventLoopGroup = new NioEventLoopGroup();
            bootstrap = new Bootstrap();
            bootstrap.group(eventLoopGroup)
                    .channel(NioSocketChannel.class)
                    .option(ChannelOption.SO_KEEPALIVE, true)
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            ch.pipeline().addLast(new StringEncoder(Charset.forName("UTF-8")))
                                    .addLast(new StringDecoder(Charset.forName("UTF-8")))
                                    .addLast(new IdleStateHandler(20, 10, 0, TimeUnit.SECONDS))
                                    .addLast(new EchoClientHandler());
                        }
                    });
            future = bootstrap.connect(host, port).sync();
            //连接成功后将重连计数器置0
            if (future.isSuccess()) {
                System.out.println("client start---------------");
                reConnectCount = 0;
            }
            //阻塞线程的退出，直到断开连接
            future.channel().closeFuture().sync();
        } catch (Exception e) {
            //e.printStackTrace();
            System.out.println("连接出错！将尝试重连！");
        } finally {
            //优雅退出，释放NIO线程组
            eventLoopGroup.shutdownGracefully();
            //关闭先前的连接，再重新进行新连接
            if (null != future) {
                if (null != future.channel() && future.channel().isOpen()) {
                    future.channel().close();
                }
            }
            //如果小于最大重连次数则进行重连
            if(reConnectCount++ < MAX_RECONNECTCOUNT){
                try {
                    int delay = reConnectCount * 2;
                    Thread.sleep(delay * 1000);
                    System.out.printf("%s秒后，第%s次重连\n", delay, reConnectCount);
                    start();
                }catch (Exception e){}
            }
        }
    }

    public static void main(String[] args) throws Exception {
        EchoClient bootstrap = new EchoClient("127.0.0.1", 8899);
        //服务器处理能力强,建立5个通道一起推消息
        for(int i =0;i<5;i++){
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    bootstrap.start();
                }
            });
            thread.start();
        }
    }
}
